﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WsHelp.UI
{
    public class RePaintColorText
    {
        public class StrSeg
        {
            public int ByteIdx;
            public int StrIdx;
            public int StrLen;
            public Color Color;
        }
        private int _colSize;
        private int _allColsSize;
        private byte[] _bytes;
        private ushort[] _strIdxs;
        private int _bytesCnt;
        private List<StrSeg> _segs = new List<StrSeg>();
        private Encoding _encoding = Encoding.GetEncoding("gb2312");

        public RePaintColorText(int bufferSize)
        {
            _bytes = new byte[bufferSize];
            _strIdxs = new ushort[_bytes.Length];
            _bytesCnt = 0;
        }

        public void Init(string str, int allColSize, int colSize)
        {
            _segs.Clear();
            _bytesCnt = _encoding.GetBytes(str, 0, str.Length, _bytes, 0);

            _allColsSize = allColSize;
            _colSize = colSize;
        }

        public void Add(string str, Color color)
        {
            if (str.Length * 2 + _bytesCnt > _bytes.Length) throw new System.Exception("即将超出缓冲区大小！");

            _segs.Add(new StrSeg() { ByteIdx = _bytesCnt, StrIdx = 0, StrLen = str.Length, Color = color });

            _bytesCnt += _encoding.GetBytes(str, 0, str.Length, _bytes, _bytesCnt);
        }

        public void Fill(int byteIdx, string str, Color color)
        {
            _segs.Add(new StrSeg() { ByteIdx = byteIdx, StrIdx = 0, StrLen = str.Length, Color = color });

            _encoding.GetBytes(str, 0, str.Length, _bytes, byteIdx);
        }

        public void Fill(int rowIdx, int colIdx, string str, Color color)
        {
            Fill((rowIdx * _allColsSize + colIdx * _colSize), str, color);
        }

        public void Show(RichTextBox rtxt)
        {
            int startLen = rtxt.TextLength;

            rtxt.AppendText(this.ToString());

            UpdateStrIdx();

            for (int i = 0; i < _segs.Count; i++)
            {
                rtxt.Select(startLen + _segs[i].StrIdx, _segs[i].StrLen);
                rtxt.SelectionColor = _segs[i].Color;
            }
        }


        public override string ToString()
        {
            return _encoding.GetString(_bytes, 0, _bytesCnt);
        }

        private void UpdateStrIdx()
        {
            ushort strIdx = 0;

            for (int i = 0; i < _bytesCnt; i++)
            {
                if (_bytes[i] > 0x7F)
                {
                    _strIdxs[i] = strIdx;
                    _strIdxs[i + 1] = strIdx;
                    i++;
                }
                else
                {
                    _strIdxs[i] = strIdx;
                }
                strIdx++;
            }

            for (int i = 0; i < _segs.Count; i++)
            {
                _segs[i].StrIdx = _strIdxs[_segs[i].ByteIdx];
            }
        }
    }
}
